﻿using System;

namespace SPFluid.Core.Validation.Extensions
{
    public static class ComparableValidatorExtensions
    {
        public static IGuard<T> IsEqual<T>(this IGuard<T> guard, T param)
            where T : IComparable
        {
            return guard.IsEqual(() => param);
        }

        public static IGuard<T> IsEqual<T>(this IGuard<T> guard, Func<T> param)
            where T : IComparable
        {
            if (guard.Argument.Value.CompareTo(param()) != 0)
            {
                guard.ExceptionHandler.ThrowArgumentOutOfRangeException();
            }

            return guard;
        }

        public static IGuard<T> IsNotEqual<T>(this IGuard<T> guard, T param)
            where T : IComparable
        {
            return guard.IsNotEqual(() => param);
        }

        public static IGuard<T> IsNotEqual<T>(this IGuard<T> guard, Func<T> param)
            where T : IComparable
        {
            if (guard.Argument.Value.CompareTo(param()) == 0)
            {
                guard.ExceptionHandler.ThrowArgumentOutOfRangeException();
            }

            return guard;
        }

        public static IGuard<T> IsGreater<T>(this IGuard<T> guard, T param)
            where T : IComparable
        {
            return guard.IsGreater(() => param);
        }

        public static IGuard<T> IsGreater<T>(this IGuard<T> guard, Func<T> param)
            where T : IComparable
        {
            if (guard.Argument.Value.CompareTo(param()) <= 0)
            {
                guard.ExceptionHandler.ThrowArgumentOutOfRangeException();
            }

            return guard;
        }

        public static IGuard<T> IsGreaterOrEqual<T>(this IGuard<T> guard, T param)
            where T : IComparable
        {
            return guard.IsGreaterOrEqual(() => param);
        }

        public static IGuard<T> IsGreaterOrEqual<T>(this IGuard<T> guard, Func<T> param)
            where T : IComparable
        {
            if (guard.Argument.Value.CompareTo(param()) < 0)
            {
                guard.ExceptionHandler.ThrowArgumentOutOfRangeException();
            }

            return guard;
        }

        public static IGuard<T> IsLess<T>(this IGuard<T> guard, T param)
            where T : IComparable
        {
            return guard.IsLess(() => param);
        }

        public static IGuard<T> IsLess<T>(this IGuard<T> guard, Func<T> param)
            where T : IComparable
        {
            if (guard.Argument.Value.CompareTo(param()) >= 0)
            {
                guard.ExceptionHandler.ThrowArgumentOutOfRangeException();
            }

            return guard;
        }

        public static IGuard<T> IsLessOrEqual<T>(this IGuard<T> guard, T param)
           where T : IComparable
        {
            return guard.IsLess(() => param);
        }

        public static IGuard<T> IsLessOrEqual<T>(this IGuard<T> guard, Func<T> param)
            where T : IComparable
        {
            if (guard.Argument.Value.CompareTo(param()) > 0)
            {
                guard.ExceptionHandler.ThrowArgumentOutOfRangeException();
            }

            return guard;
        }

        public static IGuard<T> IsInRange<T>(this IGuard<T> guard, T start, T end)
            where T : IComparable
        {
            if (guard.Argument.Value.CompareTo(start) < 0 || guard.Argument.Value.CompareTo(end) > 0)
            {
                guard.ExceptionHandler.ThrowArgumentOutOfRangeException();
            }

            return guard;
        } 
    }
}